package com.ldn.controller.api;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.ldn.basic.dispose.exception.AppException;

/**
 * @author 李大牛家的牛 (scafel@163.com)
 * @createDate 2024/7/11 - 15:35
 * @description 全局请求异常处理
 **/
@Tag(name = "全局请求异常处理", description = "全局请求异常处理")
@RestController
public class ExceptionController implements ErrorController {

    // 默认请求地址
    private static final String ERROR_PATH = "/error";

    @Operation(summary = "全局请求错误路径")
    @RequestMapping(value = ERROR_PATH, produces = MediaType.TEXT_HTML_VALUE)
    public String handlePageError() {
        int code = getStatus();
        return validateCode(code);
    }

    @Operation(summary = "全局请求异常处理")
    @RequestMapping(ERROR_PATH)
    public String handleAllError() {
        int statusCode = getStatus();
        return validateCode(statusCode);
    }

    private String validateCode(int code) {
        switch (code) {
            case 404 -> throw new AppException(404, "404-请求地址不存在");
            case 405 -> throw new AppException(405, "405-请求方法不支持");
            case 406 -> throw new AppException(406, "406-请求头信息格式错误");
            case 407 -> throw new AppException(407, "407-请求要求代理的身份验证");
            case 408 -> throw new AppException(408, "408-请求超时");
            case 409 -> throw new AppException(409, "409-请求冲突");
            case 410 -> throw new AppException(410, "410-请求的资源已经不存在");
            case 411 -> throw new AppException(411, "411-请求缺少必要请求头信息");
            case 412 -> throw new AppException(412, "412-请求前提条件失败");
            case 413 -> throw new AppException(413, "413-请求实体过大");
            case 414 -> throw new AppException(414, "414-请求的 URI 过长");
            case 415 -> throw new AppException(415, "415-请求的媒体类型不支持");
            case 416 -> throw new AppException(416, "416-请求的区间错误");
            case 417 -> throw new AppException(417, "417-请求未满足要求");
            case 418 -> throw new AppException(418, "418-I'm a teapot");
            case 422 -> throw new AppException(422, "422-请求格式正确，但是由于含有语义错误，无法响应");
            case 423 -> throw new AppException(423, "423-当前资源被锁定");
            case 424 -> throw new AppException(424, "424-请求失败");
            case 425 -> throw new AppException(425, "425-服务器拒绝执行");
            case 426 -> throw new AppException(426, "426-请求要求客户端更新");
            case 428 -> throw new AppException(428, "428-请求要求先验证");
            case 429 -> throw new AppException(429, "429-请求过多");
            case 431 -> throw new AppException(431, "431-请求头信息太大");
            case 451 -> throw new AppException(451, "451-请求被禁止");
            case 500 -> throw new AppException(500, "500-服务器内部错误");
            case 501 -> throw new AppException(501, "501-服务器不支持请求的功能");
            case 502 -> throw new AppException(502, "502-网关错误");
            case 503 -> throw new AppException(503, "503-服务器过载或维护");
            case 504 -> throw new AppException(504, "504-网关超时");
            case 505 -> throw new AppException(505, "505-服务器不支持请求的 HTTP 版本");
            case 506 -> throw new AppException(506, "506-服务器不支持请求的变体");
            case 507 -> throw new AppException(507, "507-服务器无法存储请求的资源");
            case 508 -> throw new AppException(508, "508-请求的资源被永久锁定");
            case 509 -> throw new AppException(509, "509-服务器达到带宽限制");
            case 510 -> throw new AppException(510, "510-需要扩展的机制");
            case 511 -> throw new AppException(511, "511-需要身份验证");
            default -> throw new AppException(500, "500-服务器内部错误");
        }
    }


    private Integer getStatus() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return 500;
        }
        jakarta.servlet.http.HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        Integer statusCode = (Integer) request.getAttribute("jakarta.servlet.error.status_code");
        if (statusCode == null) {
            return 500;
        }
        return statusCode;
    }

}
